from django.db.models import Sum, F
from django.db.models.signals import post_save, post_delete, post_init
from django.dispatch import receiver
from finance.models import SaleOrder, Receipt, PaymentOrder, Bank, Expense, OtherIncome, Journal, PayOrder, BorrowLend, \
    FundBill, HisBank, RepaymentBill
from finance.utils import update_account_balance

INCOME = 0
PAYMENT = 1


# 更新销售单收款金额
def update_sale_order_paid_money(instance):
    sale_order_id = instance.sale_order.id
    # 汇总实收金额
    totals = Receipt.objects.filter(sale_order_id=sale_order_id).aggregate(total_paid_money=Sum('paid_money'))
    total_paid_money = totals.get("total_paid_money", 0)
    if total_paid_money is None:
        total_paid_money = 0
    # 更新实收金额
    SaleOrder.objects.filter(id=sale_order_id).update(paid_money=total_paid_money)
    # 收款账号：未结算
    if instance.sale_order.account_type_id == 1 and instance.account_type_id > 1:
        SaleOrder.objects.filter(id=sale_order_id).update(account_type=instance.account_type)


# 更新销售单支付金额
def update_sale_order_payment_money(instance):
    sale_order_id = instance.sale_order.id
    totals = PayOrder.objects.filter(sale_order_id=sale_order_id, flag=1).aggregate(total_money=Sum('money'))
    total_money = totals.get("total_money", 0)
    if total_money is None:
        total_money = 0
    SaleOrder.objects.filter(id=sale_order_id).update(payment_money=total_money)


@receiver(post_save, sender=SaleOrder)
def insert_receipt_order(sender, instance, created, **kwargs):
    if created:
        if instance.paid_money > 0:
            order_info = {
                'sale_order': instance,
                'case_name': instance.case_name,
                'telephone': instance.telephone,
                'recv_money': instance.recv_money,
                'paid_money': instance.paid_money,
                'acc_title': instance.acc_title,
                'account_type': instance.account_type,
                'order_time': instance.order_time,
                'user': instance.user,
                'handler': instance.handler,
                'desc': instance.desc,
            }
            Receipt.objects.create(**order_info)


# 收款单初始化
@receiver(post_init, sender=Receipt)
def receipt_init(instance, **kwargs):
    instance.old_paid_money = instance.paid_money if instance.paid_money else 0
    instance.old_account_type = instance.account_type


# 收款单保存
@receiver(post_save, sender=Receipt)
def update_sale_paid_money_by_save(sender, instance, created, **kwargs):
    print('update_sale_paid_money_by_save')
    # 更改销售单实收金额和支付账号信息
    if instance.sale_order is None:
        return

    update_sale_order_paid_money(instance)

    data = {
        'order_no': instance.order_no,
        'name': instance.sale_order.customer.name if instance.sale_order.customer else "",
        'order_time': instance.order_time,
        'account_type': instance.account_type or None,
        'account_type_name': instance.account_type.account if instance.account_type else "",
        'order_type': INCOME,
        'oper_type': '收款单收款',
        'income_money': 0,
        'expense_money': 0,
        'total_money': 0,
        'user': instance.user or None,
        'acc_title': instance.acc_title or None,
        'desc': instance.desc,
    }
    print(data)
    # 增加收款单
    if created:
        # 更新账号金额
        if instance.paid_money != 0:
            update_account_balance(instance.account_type, instance.paid_money)

            data["income_money"] = instance.paid_money
            data["total_money"] = data["income_money"] + data["expense_money"]
    else:
        # 修改账号金额
        if instance.old_account_type != instance.account_type:
            update_account_balance(instance.old_account_type, -instance.old_paid_money)
            update_account_balance(instance.account_type, instance.paid_money)

            data["income_money"] = instance.paid_money
            data["total_money"] = data["income_money"] + data["expense_money"]
        else:
            paid_money = instance.paid_money - instance.old_paid_money
            if paid_money != 0:
                update_account_balance(instance.account_type, paid_money)

            data["income_money"] = instance.paid_money
            data["total_money"] = data["income_money"] + data["expense_money"]
    # 流水账记录
    create_journal(**data)


# 收款单删除
@receiver(post_delete, sender=Receipt)
def update_order_paid_money_by_delete(sender, instance, **kwargs):
    print('update_order_paid_money_by_delete')
    try:
        if instance.sale_order:
            # 更新销售单实收金额
            update_sale_order_paid_money(instance)
    except Exception as e:
        print("Exception:", e)
        pass

    # 更新账户余额
    if instance.account_type and instance.paid_money != 0:
        bank = instance.account_type
        bank.money -= instance.paid_money
        bank.save()

    remove_journal(instance.order_no)


# 付款单初始化
@receiver(post_init, sender=PayOrder)
def pay_init(instance, **kwargs):
    instance.old_money = instance.money if instance.money else 0
    instance.old_account_type = instance.account_type
    instance.old_flag = instance.flag


# 支付单保存
@receiver(post_save, sender=PayOrder)
def update_sale_payment_money_by_save(sender, instance, created, **kwargs):
    if instance.sale_order:
        update_sale_order_payment_money(instance)

    data = {
        'order_no': instance.order_no,
        'name': instance.person.name if instance.person else "",
        'order_time': instance.order_time,
        'account_type': instance.account_type or None,
        'account_type_name': instance.account_type.account if instance.account_type else "",
        'order_type': PAYMENT,
        'oper_type': '付款单付款',
        'income_money': 0,
        'expense_money': 0,
        'total_money': 0,
        'user': instance.user or None,
        'acc_title': instance.acc_title or None,
        'desc': instance.desc,
    }

    if created:
        # 更新账号金额
        if instance.flag == 1 and instance.money != 0:
            update_account_balance(instance.account_type, -instance.money)
            data["expense_money"] = instance.money
            data["total_money"] = data["income_money"] + data["expense_money"]
    else:
        # 修改账号金额
        if instance.flag == 1 and instance.old_flag == 0:   # 确认
            update_account_balance(instance.account_type, -instance.money)
        elif instance.flag == 0 and instance.old_flag == 1:     # 取消
            update_account_balance(instance.old_account_type, instance.old_money)
        elif instance.flag == instance.old_flag == 1:
            if instance.old_account_type != instance.account_type:  # 修改 银行账号及金额
                update_account_balance(instance.old_account_type, instance.old_money)
                update_account_balance(instance.account_type, -instance.money)
            else:
                diff_money = instance.money - instance.old_money    # 修改 金额
                if diff_money != 0:
                    update_account_balance(instance.account_type, -diff_money)

        data["expense_money"] = instance.money
        data["total_money"] = data["income_money"] + data["expense_money"]

    create_journal(**data)


@receiver(post_delete, sender=PayOrder)
def update_order_payment_money_by_delete(sender, instance, **kwargs):
    print('update_order_payment_money_by_delete:', instance.sale_order_id)

    try:
        if instance.sale_order:
            update_sale_order_payment_money(instance)
    except Exception as ex:
        print(ex)
        pass

    # 更新账户余额
    if instance.account_type and instance.money != 0:
        update_account_balance(instance.account_type, instance.money)

    remove_journal(instance.order_no)


def create_journal(**data):
    """保存流水信息"""
    money = data.get("total_money", 0)
    if money == 0:
        return
    order_no = data.pop("order_no")
    Journal.objects.update_or_create(order_no=order_no, defaults=data)


def remove_journal(order_no):
    """删除流水记录"""
    Journal.objects.filter(order_no=order_no).delete()


# 资金账单初始化
@receiver(post_init, sender=FundBill)
def fund_bill_init(instance, **kwargs):
    instance.old_money = instance.money if instance.money else 0
    instance.old_account_type = instance.account_type


# 资金账单保存
@receiver(post_save, sender=FundBill)
def fund_bill_update_bank_money(sender, instance, created, **kwargs):
    print('fund_bill_update_bank_money', instance.account_type)

    order_type = oper_type = None
    if instance.category == 0:      # 费用
        order_type = PAYMENT
        oper_type = '费用单付款'
    elif instance.category == 1:    # 收入
        order_type = INCOME
        oper_type = '其他收入单收款'
    elif instance.category == 2:    # 借入
        order_type = INCOME
        oper_type = '资金借入'
    elif instance.category == 3:    # 借出
        order_type = PAYMENT
        oper_type = '资金借出'

    employee_name = instance.employee.name if instance.employee else '无'
    name = instance.customer.name if instance.customer else employee_name

    data = {
        'order_no': instance.order_no,
        'name': name,
        'order_time': instance.order_time,
        'account_type': instance.account_type or None,
        'account_type_name': instance.account_type.account if instance.account_type else "",
        'order_type': order_type,
        'oper_type': oper_type,
        'income_money': 0,
        'expense_money': 0,
        'total_money': 0,
        'user': instance.user or None,
        'acc_title': instance.acc_title or None,
        'desc': instance.desc,
    }

    if instance.account_type:
        if created:
            # 增加资金借入借出单, 更新账户余额
            if instance.money != 0:
                if instance.category == 1 or instance.category == 2:
                    update_account_balance(instance.account_type, instance.money)
                    data["income_money"] = instance.money
                else:
                    update_account_balance(instance.account_type, -instance.money)
                    data["expense_money"] = instance.money
                data["total_money"] = data["income_money"] + data["expense_money"]
        else:
            # 修改资金借入借出单, 更新账户余额
            if instance.old_account_type != instance.account_type:
                if instance.category == 1 or instance.category == 2:
                    update_account_balance(instance.old_account_type, -instance.old_money)
                    update_account_balance(instance.account_type, instance.money)
                    data["income_money"] = instance.money
                else:
                    update_account_balance(instance.old_account_type, instance.old_money)
                    update_account_balance(instance.account_type, -instance.money)
                    data["expense_money"] = instance.money
                data["total_money"] = data["income_money"] + data["expense_money"]
            else:
                paid_money = instance.money - instance.old_money
                if paid_money != 0:
                    if instance.category == 1 or instance.category == 2:      # 收入/借入
                        update_account_balance(instance.account_type, paid_money)
                        data["income_money"] = instance.money
                    else:
                        update_account_balance(instance.account_type, -paid_money)
                        data["expense_money"] = instance.money

                data["income_money"] = instance.money if instance.category == 1 or instance.category == 2 else 0
                data["expense_money"] = instance.money if instance.category == 0 or instance.category == 3 else 0
                data["total_money"] = data["income_money"] + data["expense_money"]

    create_journal(**data)


# 借入借出单删除
@receiver(post_delete, sender=FundBill)
def fund_bill_bank_money_by_delete(sender, instance, **kwargs):
    print('fund_bill_bank_money_by_delete', instance.account_type)
    # 更新账户余额
    if instance.category == 1 or instance.category == 2:  # 收入/借入
        update_account_balance(instance.account_type, -(instance.money - instance.repayment))
    else:
        update_account_balance(instance.account_type, (instance.money - instance.repayment))

    remove_journal(instance.order_no)


# 还款记录
@receiver(post_save, sender=RepaymentBill)
def repayment_update_bank_money(sender, instance, created, **kwargs):
    print('repayment_update_bank_money')
    if created:
        account_type = instance.bill.account_type
        if instance.bill.category == 2:  # 借入
            if account_type:
                update_account_balance(account_type, -instance.money)

        elif instance.bill.category == 3:   # 借出
            if account_type:
                update_account_balance(account_type, instance.money)

        FundBill.objects.filter(id=instance.bill_id).update(repayment=F("repayment") + instance.money)
        bill = instance.bill
        category = bill.category

        income_money = instance.money if category == 3 else 0
        expense_money = instance.money if category == 2 else 0
        total_money = income_money + expense_money

        data = {
            'order_no': instance.order_no,
            'name': bill.employee.name,
            'order_time': instance.bill_date,
            'account_type': bill.account_type or None,
            'account_type_name': bill.account_type.account if bill.account_type else "",
            'order_type': INCOME if instance.bill.category == 3 else PAYMENT,
            'oper_type': "资金借入-还款" if instance.bill.category == 2 else "资金借出-还款",
            'income_money': income_money,
            'expense_money': expense_money,
            'total_money': total_money,
            'user': instance.user or None,
            'acc_title': None,
            'desc': instance.desc,
        }

        create_journal(**data)


# 还款记录删除
@receiver(post_delete, sender=RepaymentBill)
def repayment_bank_money_by_delete(sender, instance, **kwargs):
    print('repayment_bank_money_by_delete')
    # 更新账户余额
    try:
        if instance.bill:
            account_type = instance.bill.account_type
            if instance.bill.category == 2:  # 借入
                if account_type:
                    update_account_balance(account_type, instance.money)

            elif instance.bill.category == 3:  # 借出
                if account_type:
                    update_account_balance(account_type, -instance.money)

            FundBill.objects.filter(id=instance.bill_id).update(repayment=F("repayment") - instance.money)
    except Exception as e:
        print("Exception:", e)
        pass

    remove_journal(instance.order_no)

